#ifndef _GL_INTERFACE_HPP_
#define _GL_INTERFACE_HPP_
#include "testbedGL.hpp"
#include <vector>
#include <string>
#include <boost/shared_ptr.hpp>
#include "collada/collada.hpp"
#include "utils.hpp"

//Material framwork for Collada

//May be someday it wiil be documented. But not now since it's not stable and commentaries may mislead you.

using namespace Vectormath::Aos;
namespace GL_Interface
{


struct AlignedNodeList
{
    std::string tag;
    std::vector<boost::shared_ptr<TestbedGL::SceneNode> >nodes;
};

struct AlignedNodeListArray
{
    boost::unordered_map<std::string,AlignedNodeList>nodes;
    void build_sorted_by_material(const TestbedGL::SceneNode& node)
    {
//        for(std::vector<boost::shared_ptr<TestbedGL::SceneNode>::iterator;;)
    }
};

struct ShaderParam
{
    boost::shared_ptr<TestbedGL::ShaderVariable>variable;
    std::string type;
    virtual void pass(){throw "nothing to pass";}
};

struct SamplerSP:ShaderParam
{
    GLuint channel;
    boost::shared_ptr<TestbedGL::Texture> texture;
    void pass()
    {
        variable->pass_sampler(*texture,channel);
    }
};

struct FloatSP:ShaderParam
{
    float value;
    void pass()
    {
        variable->pass_float(value);
    }
};

struct Vec3SP:ShaderParam
{
    float r,g,b;
    void pass()
    {
        variable->pass_float3(r,g,b);
    }
};

struct Vec4SP:ShaderParam
{
    float r,g,b,a;
    void pass()
    {
        variable->pass_float4(r,g,b,a);
    }
};

typedef Vec4SP ColorSP;


struct Pass
{
//    boost::unordered_map<boost::shared_ptr<ShaderParam> >params;
    AlignedNodeList list;
   //TestbedGL::StateObject state;
    TestbedGL::RenderTarget rt;
    TestbedGL::Shader shader;
    void add_sampler(std::string name,Texture &texture,GLuint channel);
    void add_float(std::string name,float val);
    void add_float3(std::string name,float val1, float val2, float val3);
    void add_float4(std::string name,float val1, float val2, float val3, float val4);

    void draw();
};


struct Material
{
    std::vector<Pass>passes;

    void make_phong()
    {

    }

};



class GraphicsLibrary
{
private:
    boost::unordered_map<std::string,boost::shared_ptr<TestbedGL::Geometry> >geometries;
    boost::unordered_map<std::string,boost::shared_ptr<TestbedGL::SceneNode> >nodes;
    boost::unordered_map<std::string,boost::shared_ptr<TestbedGL::Texture> >textures;

public:
    void reload_resources();
    void add_texture(std::string name,std::string format);
    void add_texture_from_image(std::string name,std::string filename);
    void add_material_from_collada(std::string name, Entry &entry);
    //Lua or action script
    void add_material_from_script(std::string, std::string filename);

    void load_collada(std::string);
    void get_geometry(std::string);
    boost::shared_ptr<TestbedGL::SceneNode> get_node(std::string name)
    {
        return nodes[name];
    };
    boost::shared_ptr<TestbedGL::SceneNode> make_grid(Heightmap &map,std::string name,unsigned int size_x,unsigned int size_y,float tile_x,float tile_y,float u,float v);
    boost::shared_ptr<TestbedGL::SceneNode> make_nested_grid(Heightmap &map,std::string name,unsigned int size_x,unsigned int size_y,unsigned int hole_x,unsigned int hole_y,float tile_x,float tile_y,float u,float v);
    void get_get_material(std::string);
};
};
#endif
